package com.kevin.io.netty;

import com.kevin.io.netty.entity.User;
import com.kevin.io.netty.handler.DefaultChannelInboundHandlerAdapter;
import com.kevin.io.netty.util.ChannelHandlerUtils;
import com.kevin.io.netty.util.NettyStudyUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.CharsetUtil;

import java.nio.charset.StandardCharsets;
import java.util.Date;

/**
 * @author Kevin Liu
 */
public class NettyServer {

    public static void main(String[] args) throws InterruptedException {
        fourthTest();
    }

    public static void fourthTest() throws InterruptedException {
        //简单测试
        start(ChannelHandlerUtils.thirdTest(new DefaultChannelInboundHandlerAdapter(){
            private int count = 0;

            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                System.out.println(msg);
                System.out.println("count:"+ ++count);
                ctx.writeAndFlush(msg);
            }
        }));
    }

    /**
     * 普通Netty测试
     * @throws InterruptedException
     */
    public static void firstTest() throws InterruptedException {
        //简单测试
        start(ChannelHandlerUtils.firstTest(new DefaultChannelInboundHandlerAdapter(){
            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                ByteBuf in = (ByteBuf) msg;
                String received = in.toString(CharsetUtil.UTF_8);
                System.out.println("Sever received:" + received);
                final ByteBuf byteBuf = Unpooled.copiedBuffer(new Date().toString().getBytes(StandardCharsets.UTF_8));
                ctx.writeAndFlush(byteBuf);
            }
        }));
    }

    /**
     * 黏包测试 使用count记录
     * @throws InterruptedException
     */
    public static void secondTest() throws InterruptedException {
        //简单测试
        start(ChannelHandlerUtils.firstTest(new DefaultChannelInboundHandlerAdapter(){
            private int count = 0;

            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                ByteBuf in = (ByteBuf) msg;
                String received = in.toString(CharsetUtil.UTF_8);
                System.out.println("Sever received:" + received);
                System.out.println("count:" + ++count);
                if(NettyStudyUtils.getMessage("hello netty").equals(received)) {
                    final ByteBuf byteBuf = Unpooled.copiedBuffer(new Date().toString().getBytes(StandardCharsets.UTF_8));
                    ctx.writeAndFlush(byteBuf);
                }else{
                    final ByteBuf byteBuf = Unpooled.copiedBuffer("Bad Request".getBytes(StandardCharsets.UTF_8));
                    ctx.writeAndFlush(byteBuf);
                }
            }
        }));
    }
    /**
     * 黏包测试 使用LineBasedFrameDecoder
     * StringDecoder解决黏包拆包
     * @throws InterruptedException
     */
    public static void thirdTest() throws InterruptedException {
        //简单测试
        start(ChannelHandlerUtils.secondTest(new DefaultChannelInboundHandlerAdapter(){
            private int count = 0;

            @Override
            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                String body = (String) msg;
                System.out.println(msg);
                System.out.println("count:"+ ++count);
                if(NettyStudyUtils.getMessage("hello netty").equals(body)) {
                    final ByteBuf byteBuf = Unpooled.copiedBuffer(NettyStudyUtils.getMessage(new Date().toString()).getBytes(StandardCharsets.UTF_8));
                    ctx.writeAndFlush(byteBuf);
                }else{
                    final ByteBuf byteBuf = Unpooled.copiedBuffer(NettyStudyUtils.getMessage("Bad Request").getBytes(StandardCharsets.UTF_8));
                    ctx.writeAndFlush(byteBuf);
                }
            }

            @Override
            public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

            }
        }));
    }


    public static void start(ChannelHandler channelHandler) throws InterruptedException {

        //两个都是无限循环 bossGroup处理连接请求 workerGroup处理客户端业务请求
        //不传子线程数 则使用的是CPU核数*2
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap sb = new ServerBootstrap();
            sb.group(bossGroup, workerGroup)
                    //使用NioServerSocketChannel作为服务器的通道实现
                    .channel(NioServerSocketChannel.class)
                    //设置线程队列等待连接的个数
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    //设置保持活动连接状态
                    //.childOption(ChannelOption.SO_KEEPALIVE,true)
                    .childHandler(channelHandler);
            final ChannelFuture sync = sb.bind(8080).sync();
            sync.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
